<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Drawing with Cairo</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, Java Gnome, Cairo, drawing, Java, programming, Linux">
<meta name="description" content="Drawing with Cairo">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Drawing with Cairo</h1>

<p>
In this part of the Java programming tutorial, we will do some drawing 
with the Cairo library.
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
<b class="keyword">Cairo</b> is a library for creating 2D vector graphics. 
We can use it to draw our own widgets, charts or various effects or animations. 
</p>

<h2>Simple drawing</h2>

<p>
The stroke operation draws the outlines of shapes and the 
fill operation fills the insides of shapes. Next we will demonstrate
these two operations.
</p>

<div class="codehead">simpledrawing.java</div> 
<pre class="code">
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.Allocation;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
 * Java Gnome tutorial
 *
 * This program draws a simple
 * drawing with the Cairo library.
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class GSimpleDrawing extends Window implements Widget.ExposeEvent {

    public GSimpleDrawing() {
    
        setTitle("Simple drawing");
        
        initUI();
        
        connect(new Window.DeleteEvent() {
            public boolean onDeleteEvent(Widget source, Event event) {
                Gtk.mainQuit();
                return false;
            }
        });
        
        setDefaultSize(250, 200);
        setPosition(WindowPosition.CENTER);
        showAll();
    }
    
    public void initUI() {
        DrawingArea darea = new DrawingArea();
        darea.connect(this);
        add(darea);
    }
    
    public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
        final Context cr;
        
        cr = new Context(widget.getWindow());    
        drawShape(cr);
        
        return false;
    }
    
    public void drawShape(Context cr) {
    
        cr.setLineWidth(9);
        cr.setSource(0.7, 0.2, 0.0);
                
        int width, height;
        width = getAllocation().getWidth();
        height = getAllocation().getHeight();

        cr.translate(width/2, height/2);
        cr.arc(0, 0, (width < height ? width : height) / 2 - 10, 0, 2*Math.PI);
        cr.strokePreserve();
        
        cr.setSource(0.3, 0.4, 0.6);
        cr.fill();
    }    
    
    public static void main(String[] args) {
        Gtk.init(args);
        new GSimpleDrawing();
        Gtk.main();
    }
}
</pre>

<p>
In our example, we will draw a circle and fill it with a solid color. 
</p>

<pre class="explanation">
 DrawingArea darea = new DrawingArea();
</pre>

<p>
We will be doing our drawing operations on the <b class="keyword">DrawingArea</b> 
widget. 
</p>

<pre class="explanation">
  public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
    final Context cr;
    
    cr = new Context(widget.getWindow());    
    drawShape(cr);
    
    return false;
 }
</pre>

<p>
When the window needs to be redrawn, the <b class="keyword">ExposeEvent</b> is created.
The actual drawing is delegated to the <b class="keyword">drawShape()</b> method.
</p>

<pre class="explanation">
 cr = new Context(widget.getWindow());
</pre>

<p>
We create the <b class="keyword">Context</b> object from the
gdk window of the drawing area. The context is an
object onto which we do all our drawings. 
</p>

<pre class="explanation">
 cr.setLineWidth(9);
</pre>

<p>
We set the width of the line to 9 pixels.
</p>

<pre class="explanation">
 cr.setSource(0.7, 0.2, 0.0);
</pre>

<p>
We set the color to dark red. 
</p>

<pre class="explanation">
 int width, height;
 width = getAllocation().getWidth();
 height = getAllocation().getHeight();

 cr.translate(width/2, height/2);
</pre>

<p>
We get the width and height of the drawing area. 
We move the origin into the middle of the window. 
</p>

<pre class="explanation">
 cr.arc(0, 0, (width < height ? width : height) / 2 - 10, 0, 2*Math.PI);
 cr.strokePreserve();
</pre>

<p>
We draw the outside shape of a circle. The <b class="keyword">strokePreserve()</b> 
strokes the current path according to the current line width, line join, line cap,
and dash settings. Unlike the <b class="keyword">stroke()</b>, it preserves 
the path within the cairo context. 
</p>

<pre class="explanation">
 cr.setSource(0.3, 0.4, 0.6);
 cr.fill();
</pre>

<p>
This fills the interior of the circle with some blue color.
</p>


<br>
<img src="/img/gui/javagnome/simpledrawing.png" alt="Simple drawing">
<div class="figure">Figure: Simple drawing</div>
<br>


<h2>Basic shapes</h2>

<p>
The next example draws some basic shapes onto the window. 
</p>

<div class="codehead">basicshapes.java</div> 
<pre class="code">
package com.zetcode;

import org.freedesktop.cairo.Context;
import org.freedesktop.cairo.Matrix;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;


/**
 * ZetCode Java Gnome tutorial
 *
 * This program draws basic shapes
 * with the cairo library.
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class GBasicShapes extends Window implements Window.ExposeEvent {

    public GBasicShapes() {
    
        setTitle("Basic Shapes");
        
        initUI();
        
        connect(new Window.DeleteEvent() {
            public boolean onDeleteEvent(Widget source, Event event) {
                Gtk.mainQuit();
                return false;
            }
        });
    
        setDefaultSize(390, 240);
        setPosition(WindowPosition.CENTER);
        showAll();
    }
    
    public void initUI() {
        DrawingArea darea = new DrawingArea();
        darea.connect(this);
        add(darea);
    }
    
    public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
        final Context cr;
        
        cr = new Context(widget.getWindow());    
        drawShapes(cr);
        
        return false;
    }
    
    public void drawShapes(Context cr) {
    
        cr.setSource(0.6, 0.6, 0.6);

        cr.rectangle(20, 20, 120, 80);
        cr.rectangle(180, 20, 80, 80);
        cr.fill();

        cr.arc(330, 60, 40, 0, 2*Math.PI);
        cr.fill();

        cr.arc(90, 160, 40, Math.PI/4, Math.PI);
        cr.fill();
        
        Matrix mat = new Matrix();
        mat.translate(220, 180);        
        mat.scale(1, 0.7);
        cr.transform(mat);
      
        cr.arc(0, 0, 50, 0, 2*Math.PI);
        cr.fill();  
    }
    
    public static void main(String[] args) {
        Gtk.init(args);
        new GBasicShapes();
        Gtk.main();
    }
}
</pre>

<p>
In this example, we will create a rectangle, a square, 
a circle, an arc and an ellipse. 
</p>

<pre class="explanation">
 cr.rectangle(20, 20, 120, 80);
 cr.rectangle(180, 20, 80, 80);
 cr.fill();
</pre>

<p>
 These lines draw a rectangle and a square. 
</p>

<pre class="explanation">
 cr.arc(330, 60, 40, 0, 2*Math.PI);
 cr.fill();
</pre>

<p>
Here the <b class="keyword">arc()</b> method draws a full circle.
</p>

<pre class="explanation">
 Matrix mat = new Matrix();
 mat.translate(220, 180);        
 mat.scale(1, 0.7);
 cr.transform(mat);
      
 cr.arc(0, 0, 50, 0, 2*Math.PI);
 cr.fill();  
</pre>

<p>
If we want to draw an oval, we do some scaling first. 
The <b class="keyword">scale()</b> method shrinks the y axis.
</p>


<br>
<img src="/img/gui/javagnome/basicshapes.png" alt="Basic shapes">
<div class="figure">Figure: Basic shapes</div>
<br>


<h2>Colors</h2>

<p>
A color is an object representing a combination of Red, Green, and Blue (RGB) intensity values.
Cairo valid RGB values are in the range 0 to 1. 
</p>

<div class="codehead">colors.java</div> 
<pre class="code">
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
 * ZetCode Java Gnome tutorial 
 *
 * This program draws nine rectangles
 * on the drawing area. Each of them
 * has different color. 
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class GColors extends Window
            implements Widget.ExposeEvent {
    
    public GColors() {
    
        setTitle("Colors");
    
        connect(new Window.DeleteEvent() {
            public boolean onDeleteEvent(Widget source, Event event) {
                Gtk.mainQuit();
                return false;
            }
        });
        
        initUI();
        
        setDefaultSize(350, 280);
        setPosition(WindowPosition.CENTER);
        showAll();
    }
    
    public void initUI() {
        DrawingArea darea = new DrawingArea();
        darea.connect(this);
        add(darea);
    }

    public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
        final Context cr;
    
        cr = new Context(widget.getWindow());
        drawRectangles(cr);       
 
        return false;
    }
    
    
    public void drawRectangles(Context cr) {
        cr.setSource(0.5, 0.65, 0.45);
        cr.rectangle(10, 15, 90, 60);
        cr.fill();

        cr.setSource(0.16, 0.7, 0.9);
        cr.rectangle(130, 15, 90, 60);
        cr.fill();

        cr.setSource(0.274, 0.262, 0.48);
        cr.rectangle(250, 15, 90, 60);
        cr.fill();

        cr.setSource(0.5, 0.39, 0.33);
        cr.rectangle(10, 105, 90, 60);
        cr.fill();
        
        cr.setSource(0.99, 0.83, 0.24);
        cr.rectangle(130, 105, 90, 60);
        cr.fill();
        
        cr.setSource(0.95, 0.38, 0.27);
        cr.rectangle(250, 105, 90, 60);
        cr.fill();
        
        cr.setSource(0.85, 0.57, 0.21);
        cr.rectangle(10, 195, 90, 60);
        cr.fill();
        
        cr.setSource(0.25, 0.04, 0.73);
        cr.rectangle(130, 195, 90, 60);
        cr.fill();
        
        cr.setSource(0.12, 0.08, 0.03);
        cr.rectangle(250, 195, 90, 60);
        cr.fill();
    }
    
    public static void main(String[] args)  {
        Gtk.init(args);
        new GColors();
        Gtk.main();
    }
}
</pre>

<p>
We draw nine rectangles in nine different colors.
</p>

<pre class="explanation">
 cr.setSource(0.5, 0.65, 0.45);
</pre>

<p>
The <b class="keyword">setSource()</b> method sets a color for the 
cairo context. The three parameters of the method are the color intensity
values. 
</p>

<pre class="explanation">
 cr.rectangle(10, 15, 90, 60);
 cr.fill();
</pre>

<p>
We create a rectangle shape and fill it with the previously specified 
color. 
</p>

<br>
<img src="/img/gui/javagnome/colors.png" alt="Colors">
<div class="figure">Figure: Colors</div>
<br>


<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material. 
The easiest way to understand transparency is to imagine a piece 
of glass or water. Technically, the rays of light can go
through the glass and this way we can see objects behind the glass.
</p>
<p>
In computer graphics, we can achieve transparency effects using 
alpha compositing. Alpha compositing is the process of combining 
an image with a background to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com)
</p>

<div class="codehead">transparentrectangles.java</div>
<pre class="code">
package com.zetcode;

import org.freedesktop.cairo.Context;

import org.gnome.gdk.Event;
import org.gnome.gdk.EventExpose;
import org.gnome.gtk.DrawingArea;
import org.gnome.gtk.Gtk;
import org.gnome.gtk.Widget;
import org.gnome.gtk.Window;
import org.gnome.gtk.WindowPosition;

/**
 * ZetCode Java Gnome tutorial
 *
 * This program draws ten rectangles
 * with different levels of transparency.
 *
 * @author jan bodnar
 * website zetcode.com
 * last modified March 2009
 */

public class GTransparentRectangles extends Window
    implements Widget.ExposeEvent {

    public GTransparentRectangles() {
        setTitle("Transparent Rectangles");
        
        connect(new Window.DeleteEvent() {
            public boolean onDeleteEvent(Widget source, Event event) {
                Gtk.mainQuit();
                return false;
            }
        });
        
        initUI();
        
        setSizeRequest(590, 90);
        setPosition(WindowPosition.CENTER);
        showAll();
    }
    
    
    public void initUI() {
        DrawingArea darea = new DrawingArea();
        add(darea);
        darea.connect(this);
    }
 

    public void doDrawing(Context cr) {
    
        for (int i = 1; i<=10; i++) {
            cr.setSource(0, 0, 1, 0.1*i);
            cr.rectangle(50*i, 20, 40, 40);
            cr.fill();
        }
    }

    public boolean onExposeEvent(Widget widget, EventExpose eventExpose) {
        
            Context cr = new Context(widget.getWindow());
            doDrawing(cr);
            
            return false;
    }
    
    public static void main(String[] args) {
        Gtk.init(args);
        new GTransparentRectangles();
        Gtk.main();
    }
}
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>

<pre class="explanation">
 cr.setSource(0, 0, 1, 0.1*i);
</pre>

<p>
The last parameter of the <b class="keyword">setSource()</b> method is the
alpha transparency.
</p>


<br>
<img src="/img/gui/javagnome/transparency.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>
<br>

<hr class="btm">

<p>
In this chapter of the Java Gnome programming library, we were drawing 
with Cairo library.
</p>


<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified March 12, 2009  <span class="copyright">&copy; 2007 - 2012 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>

